package com.mew.chess.core.common.handler;

import com.mew.chess.core.common.message.request.EnterGameRequestMessage;
import com.mew.chess.core.common.message.request.ReconnectionGameRequestMessage;
import com.mew.common.dc.redis.AucRedisService;
import com.mew.common.dc.redis.EnterRoomCheckService;
import com.mew.common.dc.redis.GameRoomRedisService;
import com.mew.common.enm.ExitType;
import com.mew.common.exception.ResponseCode;
import com.mew.common.rest.LongMessage;
import com.mew.common.rest.PlayingMessage;
import com.mew.common.rest.bo.GameSession;
import com.mew.common.rest.game.ChessEnterRoomResponse;
import com.mew.common.rest.bo.MewSession;
import com.mew.common.util.StringUtils;
import com.zebra.remoting.config.BasisCommandCode;
import com.zebra.remoting.config.EmptyMessage;
import com.zebra.remoting.protocol.ZebraCommand;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
@Slf4j
public abstract class AbstractEnterExitHandler implements ChessEEHandler {
    @Autowired
    private EnterExitRoomService enterExitRoomService;
    @Autowired
    private EnterRoomCheckService enterRoomCheckService;
    @Autowired
    private AucRedisService aucRedisService;
    @Autowired
    private ChessSessionManager chessSessionManager;
    @Autowired
    private GameRoomRedisService gameRoomRedisService;
    @Autowired
    private MewGameConfig mewGameConfig;

    @Override
    public void enterRoom(ZebraCommand<EnterGameRequestMessage> command, MewSession session, GameSession chessSession) {
        doEnterRoom(command, command.getRequest().getRoomId(), session, chessSession, ChessHandlerMapCmdType.EnterRoom);
    }

    @Override
    public void reconnectRoom(ZebraCommand<ReconnectionGameRequestMessage> command, MewSession session, GameSession chessSession) {
        ReconnectionGameRequestMessage requestMessage = command.getRequest();
        if (null == requestMessage){
            command.sendFailureCode(ResponseCode.ParamInvalid.code());
            return;
        }
        boolean check = StringUtils.checkMewStr(requestMessage.getEncryptionStr(), mewGameConfig.getLobbyKey(), mewGameConfig.getLobbyCode(), command.getToken(), requestMessage.getStartTime());
        if (!check){
            command.sendFailureCode(ResponseCode.ParamInvalid.code());
            return;
        }
        doEnterRoom(command, requestMessage.getRoomId(), session, chessSession, ChessHandlerMapCmdType.ReconnectRoom);
    }


    private void doEnterRoom(ZebraCommand command, int roomId, MewSession session, GameSession chessSession, ChessHandlerMapCmdType cmdType){
        if (command.getUserId() <1 || command.getGameId() <1 || roomId <1){
            command.sendFailureCode(ResponseCode.ParamInvalid.code());
            return;
        }

        if (session.checkChessPlaying() && session.rid != roomId){
            PlayingMessage message = gameRoomRedisService.getPlayInfo(session.gid, session.rid);
            message.setRemainTime(session.remainingLock());
//            if (message.getStateCode() != ResponseCode.Success.code()){
//             如果该房间失效 需要退出
//            }
            chessSession = null == chessSession ?  new GameSession() : chessSession;
            chessSession.setUserId(command.getUserId());
            chessSession.setTk(command.getToken());
            chessSession.setChannel(command.getChannel());
            ChessPushMessageUtil.pushMessage(chessSession, BasisCommandCode.PLAYING.cmd(), message);
            return;
        }

        if (cmdType == ChessHandlerMapCmdType.ReconnectRoom && (session.rioid == -9 || session.rid != roomId)){
            command.sendFailureCode(ResponseCode.LoginUn.code());
            return;
        }

        chessSession = null == chessSession ? new GameSession() : chessSession;
        ResponseCode responseCode = enterRoomCheckService.checkEnterRoom(command.getUserId(), command.getGameId(), roomId, chessSession);
        if (ResponseCode.Success != responseCode){
            command.sendFailureCode(responseCode.code());
            return;
        }

        responseCode = doSitDown(roomId, chessSession, session, false); //do sitDown
        if (responseCode != ResponseCode.Success){
            command.sendFailureCode(responseCode.code());
            return;
        }

        ChessEnterRoomResponse enterRoomResponse;
        if (-9 == session.rioid){
            enterRoomResponse = enterExitRoomService.doFeignEnterRoom(chessSession, command, roomId,1);
        }else {
            if (cmdType == ChessHandlerMapCmdType.ReconnectRoom){
                enterRoomResponse = enterExitRoomService.doFeignEnterRoom(chessSession, command, roomId,3);
            }else {
                enterRoomResponse = enterExitRoomService.doFeignEnterRoom(chessSession, command, roomId,2);
            }
        }

        if (ResponseCode.Success.code() != enterRoomResponse.getErrorState()){
            log.error("Enter Error {}", chessSession.toString());
            command.sendFailureCode(enterRoomResponse.getErrorState());
            return;
        }

        buildChessSession(chessSession, command.getChannel(), enterRoomResponse.getGoldNumber());
        doFinish(chessSession, command, enterRoomResponse);
    }

    private void buildChessSession(GameSession chessSession, Channel channel, long goldNumber){
        MewSession session = aucRedisService.getSession(chessSession.getUserId());
        chessSession.setTk(session.tk);
        chessSession.setInoutId(session.rioid);
        chessSession.setChannel(channel);

        chessSession.setGameId(session.gid);
        chessSession.setRoomId(session.rid);
        chessSession.setTableId(session.tid);
        chessSession.setSeatNo(session.sno);
        chessSession.setWeakClose(false);

        chessSessionManager.put(chessSession);

        chessSession.setGoldNumber(goldNumber);
    }

    @Override
    public void exit(ZebraCommand<EmptyMessage> zebraCommand, MewSession session, GameSession chessSession){
        long userId = zebraCommand.getUserId();
        if (doExitRoom(session, chessSession.getRoomId())){
            zebraCommand.sendFailureCode(ResponseCode.ChessPaying.code());
            return;
        }
        chessSession.setWeakClose(true);
        enterExitRoomService.exitRoom(userId, ExitType.Exit.code());
        chessSessionManager.remove(chessSession);
        zebraCommand.sendMessage(new LongMessage(chessSession.getGoldNumber()));
    }

    @Override
    public void expiredExit(long userId, int gameId, int roomId){
        MewSession mewSession = new MewSession();
        mewSession.uid = userId;
        doExitRoom(mewSession, roomId); //对应游戏操作
        enterExitRoomService.exitRoom(userId, ExitType.Expires.code());
        chessSessionManager.remove(userId);
    }


    //处理 子游戏 坐下 true 重连  false进入游戏
    public abstract ResponseCode doSitDown(int roomId, GameSession chessSession, MewSession session, boolean isRepeat);

    public abstract void doFinish(GameSession chessSession, ZebraCommand command, ChessEnterRoomResponse enterRoomResponse);

    public abstract boolean doExitRoom(MewSession session, int roomId);


}
